import os
import configparser
from pathlib import Path


class ConfigManager:
    """
    配置管理类，用于从properties文件读取配置信息并提供给其他类使用
    """
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(ConfigManager, cls).__new__(cls)
            cls._instance._initialized = False
        return cls._instance

    def __init__(self, config_file=None):
        if self._initialized:
            return
        
        # 加载配置文件路径
        self.config_file = self._get_config_file_path(config_file)
        self._load_config()
        self._initialized = True

    def _get_config_file_path(self, config_file=None):
        """
        获取配置文件路径，按照以下优先级：
        1. 参数传入的路径
        2. 环境变量指定的路径
        3. 预定义的可能路径列表
        
        Returns:
            str: 配置文件路径
        """
        # 1. 如果直接传入配置文件路径，则优先使用
        if config_file and os.path.exists(config_file):
            return config_file
            
        # 2. 检查环境变量中是否指定了配置文件路径
        env_config_path = os.environ.get('CONFIG_FILE_PATH')
        if env_config_path and os.path.exists(env_config_path):
            return env_config_path
            
        # 3. 搜索可能的配置文件路径
        # 获取当前文件所在目录
        current_dir = Path(__file__).parent
        possible_paths = [
            # 开发环境路径
            os.path.join(current_dir.parent, 'config.properties'),            # app/config.properties
            os.path.join(current_dir.parent.parent, 'config.properties'),     # backend/config.properties
            os.path.join(current_dir.parent.parent.parent, 'config.properties'),  # 项目根目录/config.properties
            
            # 可能的生产环境路径
            '/etc/maling-console/config.properties',
            os.path.join(os.path.expanduser('~'), '.maling-console', 'config.properties')
        ]
        
        # 根据当前环境添加特定配置文件
        env = os.environ.get('ENV', 'development')
        env_specific_paths = [
            os.path.join(current_dir.parent, f'config.{env}.properties'),
            os.path.join(current_dir.parent.parent, f'config.{env}.properties'),
            os.path.join(current_dir.parent.parent.parent, f'config.{env}.properties')
        ]
        possible_paths.extend(env_specific_paths)
        
        # 检查所有可能的路径
        for path in possible_paths:
            if os.path.exists(path):
                return path
                
        # 如果找不到任何配置文件，默认使用app下的配置文件路径（即使不存在）
        return os.path.join(current_dir.parent, 'config.properties')

    def _load_config(self):
        """加载配置文件"""
        config = configparser.ConfigParser()
        
        # 如果配置文件存在，则读取配置
        if os.path.exists(self.config_file):
            config.read(self.config_file, encoding='utf-8')
            print(f"已加载配置文件: {self.config_file}")
        else:
            print(f"警告: 配置文件不存在 - {self.config_file}")
        
        # NebulaGraph配置
        self.nebula_config = {
            "ip": self._get_config(config, 'NEBULA', 'ip'),
            "port": self._get_config_int(config, 'NEBULA', 'port'),
            "user": self._get_config(config, 'NEBULA', 'user'),
            "password": self._get_config(config, 'NEBULA', 'password'),
            "space": self._get_config(config, 'NEBULA', 'space')
        }

        # Milvus配置
        self.milvus_config = {
            # Milvus服务器连接
            "uri": self._get_config(config, 'MILVUS', 'uri'),
            "token": self._get_config(config, 'MILVUS', 'token'),
            # Milvus Lite本地连接
            "collection_name": self._get_config(config, 'MILVUS', 'collection_name'),
            "dimension": self._get_config_int(config, 'MILVUS', 'dimension')
        }

        # 嵌入模型配置
        self.embedding_config = {
            "model_name": self._get_config(config, 'EMBEDDING', 'model_name'),
            "api_key": self._get_config(config, 'EMBEDDING', 'api_key'),
            "api_base": self._get_config(config, 'EMBEDDING', 'api_base')
        }

        # LLM配置
        self.llm_config = {
            "model": self._get_config(config, 'LLM', 'model'),
            "api_key": self._get_config(config, 'LLM', 'api_key'),
            "api_base": self._get_config(config, 'LLM', 'api_base')
        }

        # 文档服务配置
        self.documentation_config = {
            "host": self._get_config(config, 'DOCUMENTATION', 'host'),
            "port": self._get_config_int(config, 'DOCUMENTATION', 'port'),
            "api_base": self._get_config(config, 'DOCUMENTATION', 'api_base')
        }

    def _get_config(self, config, section, option):
        """
        获取配置项，如果不存在则返回None
        
        Args:
            config: configparser对象
            section: 配置节
            option: 配置项
            
        Returns:
            配置值
        """
        env_key = f"{section}_{option}".upper()
        
        # 优先从环境变量获取
        env_value = os.environ.get(env_key)
        if env_value is not None:
            return env_value
        
        # 其次从配置文件获取
        try:
            return config.get(section, option)
        except (configparser.NoSectionError, configparser.NoOptionError):
            return None

    def _get_config_int(self, config, section, option):
        """
        获取整型配置项
        
        Args:
            config: configparser对象
            section: 配置节
            option: 配置项
            
        Returns:
            整型配置值或None
        """
        value = self._get_config(config, section, option)
        if value is not None:
            try:
                return int(value)
            except (ValueError, TypeError):
                return None
        return None

    def reload(self):
        """重新加载配置"""
        self._load_config()
        
    def get_config_file_path(self):
        """获取当前使用的配置文件路径"""
        return self.config_file


# 单例实例
config = ConfigManager() 